/*
 * SpeedoGradient - Speedometer and gradient  meter application for Android 
 * Copyright 2013 Guilhem VALENTIN
 * 
 * This file is part of SpeedoGradient
 * 
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 * 
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
 * GNU General Public License for more details.
 * 
 * You should have received a copy of the GNU General Public License
 * along with SpeedoGradient. If not, see <http://www.gnu.org/licenses/>.
 */
package com.gvalentin.speedogradient.util;

import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.ListIterator;

/**
 * Rolling list of DistanceElevation elements
 * Introduce new methods specific to this type of element
 * @author guilhem
 */
public class DistanceRollingList implements RollingList<DistanceElevation> {
	
	// Maximum total distance
	protected double maxDistance;
	
	// List of DistanceElevation pairs
	protected List<DistanceElevation> deItems;
	
	// Total amount
	protected double totalDistance;
	
	/**
	 * Constructor
	 */
	public DistanceRollingList(double maxDistance) {
		this.maxDistance = maxDistance;
		this.deItems = new ArrayList<DistanceElevation>();
	}
	
	/**
	 * Overrides add method to optimize average calculation
	 * @see com.gvalentin.SpeedoGradient.util.RollingList#add(java.lang.Object)
	 */
	@Override
	public synchronized boolean add(DistanceElevation de) {
		if (de == null) {
			return false;
		}
		
		// Check that we did not reach maximum distance
		totalDistance += de.distance;
        while (totalDistance > maxDistance) {
    		try {
    			removeHint(0, deItems.get(0));
    		} catch (Exception e) { }
    		deItems.remove(0);
        }
        
        return deItems.add(de);
	}

	/**
	 * Remove item value when removing
	 */
	protected void removeHint(int index, DistanceElevation value) {
		totalDistance -= value.distance;
	}
	
	/**
	 * Get total distance
	 */
	public double getTotalDistance() {
		return totalDistance;
	}
	
	/**
	 * Gets current size of the list
	 * @return
	 */
	@Override
	public int size() {
		return deItems.size();
	}
	
	/**
	 * Indicate whether list is empty
	 * @return
	 */
	@Override
	public boolean isEmpty() {
		return deItems.isEmpty();
	}
	
    /**
     * Retrieves the item at the specified index in this list.
     * @param index The index to look up
     * @return The item at the specified index
     */
	@Override
    public DistanceElevation get(final int index) {
        return deItems.get(index);
    }
    
	/**
     * Retrieves the last item in this list.
     * @param index The index to look up
     * @return The item at the last index
	 */
	@Override
	public DistanceElevation getLast() {
		if (!deItems.isEmpty()) {
			return deItems.get(deItems.size()-1);
		} else {
			return null;
		}
	}
	
	/**
	 * Get iterator on list
	 */
	@Override
	public Iterator<DistanceElevation> iterator() {
		return deItems.iterator();
	}
	
	/**
	 * Get iterator on list
	 */
	@Override
	public ListIterator<DistanceElevation> listIterator() {
		return deItems.listIterator();
	}
}
